#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <time.h>

pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; //静态锁
pthread_cond_t *ct ;
pthread_t ntid_1 = 0;
pthread_t ntid_2 = 1;
int common = 1;

void printpid(void);
void *thr_fn_1(void* );
void *thr_fn_2(void* );

void cleanup(void *arg)
{
    printf("cleanup func : %s\n", (char *)arg);
}

void printpid()
{
    pid_t pid;
    pthread_t tid;
    pid = getpid();
    tid = pthread_self();
    printf("pid = %u, tid = %u\n", (unsigned int)pid, (unsigned int)tid);
}

void *thr_fn_1(void* arg)
{
    printf("pthread one start\n");
    pthread_cleanup_push(cleanup, "thread 1 first handler");
    pthread_mutex_lock(&mx);   //给线程加锁
    printf("thread 1 push complete. \n");
    common += 1;
    printf("common = %d\n", common);
    printpid();
    sleep(3);              
    common += 1;
    printf("common = %d\n", common);
    pthread_cleanup_pop(1);
    printf("pthread one end\n");
    pthread_mutex_lock(&mx);   //解锁线程
    pthread_cond_signal(ct);   //执行完后发送信号
    return ((void*)1);
}

void *thr_fn_2(void* arg)
{
    printf("pthread two start\n");
    pthread_cleanup_push(cleanup, "thread 2 first handler");
    while(1){
        pthread_cond_wait(ct, &mx);  //得到信号继续执行
        break;
    }
    common -= 1;
    printf("common = %d\n", common);
    printf("thread 2 push complete. \n");
    printpid();
    pthread_cleanup_pop(1);
    printf("pthread two end\n");
    pthread_exit((void *)2);
}

int main(void)
{
    int err;
    void *tret;
    ct = malloc(sizeof(pthread_cond_t));  
    pthread_cond_init(ct, NULL); //初始化条件变量
    err = pthread_create(&ntid_1, NULL, thr_fn_1, NULL);
    if (err != 0) printf("err 1\n");

    err = pthread_create(&ntid_2, NULL, thr_fn_2, NULL);
    if (err != 0) printf("err 1\n");

    if( pthread_join(ntid_1, &tret) == EINVAL ) printf("has detach !\n");
    printf("thread 1 exit code %d\n", (int)tret);

    pthread_join(ntid_2, &tret);
    printf("thread 2 exit code %d\n", (int)tret);

    pthread_cond_destroy(ct);  //动态分配需要释放条件变量
    printf("main\n");
    printpid();
    exit(0);
}
